import React, { useRef } from "react"
import { View, Input, Image } from "@tarojs/components"
import GpContainer from "@/components/GpContainer"
import Icon from "@/components/GpFontIcon"
import Taro, { useReachBottom, useRouter } from "@tarojs/taro"
import { useSetState } from "@/utils/hooks"
import { historyStack } from "./history"
import styles from "./index.module.scss"
import clsx from "clsx"
import GpInstitutionItem from "@/components/GpInstitutionItem"
import { searchInstitution, searchNews, searchNotes, searchWordTopic } from "@/apis/yikao-community"
import { requestIsFullfilled } from "@/utils/request"
import GpEmpty from "@/components/GpEmpty"
import { navigation } from "@/utils/router"
import { pageMapper, pageMapperCommunity } from "@/constants/pageMap"
import GpNoteItem from "../../note/components/GpNoteItem"
import ImageCascade from "../components/imageCascade"
import styles1 from "../wordsquare/index.module.scss"

type ListType =
  | IApiRelative.ISearchInstitution.IInstitutionListItem[]
  | IApiRelative.ISearchNews.INewsListItem[]
  | IApiRelative.ISearchWordTopic.IWordTopicListItem[]
  | IApiRelative.ISearchNotes.INoteListItem[]
type IState = {
  searchValue?: string
  histories: string[]
  list: ListType
  hasMore: boolean
  current: number
  filter: Filter
  renderList: boolean
  focused: boolean
}
enum Filter {
  Institutions = 0,
  News = 1,
  Topics = 2,
  Notes = 3
}
type IParams = {
  /**
   * 来源页面
   * - community: 仅显示笔记列表
   */
  from?: "community"
}
/**
 * @page 搜索页
 */
export default function HomeSearch() {
  const router = useRouter<IParams>()
  const filters = useRef<IOptionLike<Filter>[]>(
    router.params.from === "community"
      ? [{ value: Filter.Notes, label: "笔记" }]
      : [
          { value: Filter.Institutions, label: "机构" },
          { value: Filter.News, label: "资讯" },
          { value: Filter.Topics, label: "话题" },
          { value: Filter.Notes, label: "笔记" }
        ]
  )
  const [state, setState, stateRef] = useSetState<IState>(
    {
      searchValue: "",
      histories: historyStack.get(),
      list: [],
      hasMore: true,
      current: 1,
      filter: filters.current[0].value,
      renderList: false,
      focused: true
    },
    true
  )
  useReachBottom(() => {
    if (stateRef.current!.hasMore) {
      setState({ current: stateRef.current!.current + 1 })
      handleSeach()
    }
  })
  function handleInputConfirm() {
    let histories = stateRef.current!.histories
    if (stateRef.current!.searchValue) {
      histories = historyStack.push(stateRef.current!.searchValue)
    }
    setState({ current: 1, list: [], renderList: true, histories })
    handleSeach()
  }
  function handleSeach() {
    Taro.showLoading({ title: "搜索中..." })
    let action: any = null
    const params = {
      pagination: {
        current: stateRef.current!.current,
        pageSize: 10
      },
      sort: {
        predicate: "",
        reverse: false
      },
      search: {
        name: stateRef.current!.searchValue
      }
    }
    if (stateRef.current!.filter === Filter.Institutions) {
      // 按机构更新时间倒序（从上到下）排序
      params.sort.predicate = "updateTime"
      params.sort.reverse = true
      action = searchInstitution(params)
    } else if (stateRef.current!.filter === Filter.News) {
      // 按发布时间倒序（从上到下）排序
      params.sort.predicate = "updateTime"
      params.sort.reverse = true
      action = searchNews(params)
    } else if (stateRef.current!.filter === Filter.Topics) {
      // 按更新时间倒序（从上到下）排序
      params.sort.predicate = "updatedTime"
      params.sort.reverse = true
      action = searchWordTopic(params)
    } else if (stateRef.current!.filter === Filter.Notes) {
      // 按笔记发布时间倒序（从上到下）排序
      params.sort.predicate = "publishedTime"
      params.sort.reverse = true
      action = searchNotes(params)
    }
    if (action) {
      action
        .then(res => {
          Taro.hideLoading()
          if (requestIsFullfilled(res)) {
            const { list, pagination } = res.data.data
            setState({
              list: pagination.current === 1 ? list : [...stateRef.current!.list, ...list],
              hasMore: pagination.current < pagination.pageCount
            })
          }
        })
        .catch(() => {
          Taro.hideLoading()
        })
    }
  }
  function handleClickHistory(history: string) {
    setState({ searchValue: history, renderList: true, list: [], current: 1 })
    handleSeach()
  }
  function handleClickCancel() {
    setState({
      searchValue: "",
      renderList: false
    })
  }
  function handleClearHistory() {
    Taro.showModal({
      content: "确定要清空历史搜索记录吗？",
      success({ confirm }) {
        if (confirm) {
          setState({
            histories: []
          })
          historyStack.clear()
        }
      }
    })
  }
  function handleClickFilter(filter: IOptionLike<Filter>) {
    if (filter.value === state.filter) return
    setState({
      filter: filter.value,
      current: 1,
      list: [],
      renderList: true
    })
    handleSeach()
  }
  function handleLike(noteItem: PrimaryKey<number>, meta: IApiRelative.INoteLikeSwitch.IResData) {
    const _list = stateRef.current!.list.concat() as IApiRelative.ISearchNotes.INoteListItem[]
    const finder = _list.find(item => item.id === noteItem.id)
    if (finder) {
      finder.isSelfLike = meta.isLike
      finder.likeCount = meta.likeCount
      setState({ list: _list })
    }
  }
  function renderSearchPanel() {
    return (
      <View className={styles.searhWrapper}>
        <View className={styles.searchInput}>
          <Icon
            icon="icon-shouye-sousuo"
            color="#BBBBBB"
            size={32}
            className="text-center cursor-pointer"
          />
          <Input
            focus={state.focused}
            placeholder="请输入要搜索的内容"
            value={state.searchValue}
            confirmType="search"
            placeholderStyle="color: #BBBBBB;"
            className={styles.input}
            onInput={ev => setState({ searchValue: ev.detail.value })}
            onConfirm={handleInputConfirm}
            onBlur={() => setState({ focused: false })}
            onFocus={() => setState({ focused: true })}
          />
        </View>
        <View className={styles.cancelText} onClick={handleClickCancel}>
          取消
        </View>
      </View>
    )
  }
  function renderSearchHistory() {
    if (state.histories.length === 0) return null
    return (
      <View className="box-border px-32px pb-32px">
        <View className="flex flex-row justify-between items-center pt-16px pb-24px">
          <View className="text-28px text-light">搜索历史</View>
          <Icon
            icon="icon-youjiancaidan-shanchu"
            color="#999999"
            size={28}
            onClick={handleClearHistory}
          />
        </View>
        <View className="flex flex-row flex-wrap box-border gap-16px">
          {state.histories.map(l => (
            <View className={styles.history} key={l} onClick={() => handleClickHistory(l)}>
              {l}
            </View>
          ))}
        </View>
      </View>
    )
  }
  function renderFilters() {
    if (filters.current.length <= 1) return null
    return (
      <View className={styles.filters}>
        {filters.current.map(l => (
          <View
            key={l.value}
            className={clsx(styles.filter, {
              [styles.filterActive]: l.value === state.filter
            })}
            onClick={() => handleClickFilter(l)}
          >
            {l.label}
          </View>
        ))}
      </View>
    )
  }
  function renderLists() {
    if (!state.renderList) return null
    if (state.list.length === 0) {
      return <GpEmpty />
    }
    if (state.filter === Filter.Institutions) {
      return renderInstitutions()
    } else if (state.filter === Filter.News) {
      return renderNews()
    } else if (state.filter === Filter.Topics) {
      return renderTopics()
    } else if (state.filter === Filter.Notes) {
      return renderNotes()
    }
    return null
  }
  function renderInstitutions() {
    const institutions = state.list as IApiRelative.ISearchInstitution.IInstitutionListItem[]
    return (
      <View className="bg-white">
        {institutions.map(l => (
          <GpInstitutionItem
            key={l.id}
            pureProps={{
              institution: {
                id: l.id,
                distance: 0,
                logo: l.pic,
                name: l.name,
                // projects: l.projectNames,
                rate: l.score,
                // 最多前 3 条
                tags: l.subjectTag.slice(0, 3),
                views: l.viewCount
              }
            }}
            className={clsx(styles.institutionItem, styles.seperatorLine)}
          />
        ))}
      </View>
    )
  }
  function renderNews() {
    const news = state.list as IApiRelative.ISearchNews.INewsListItem[]
    return (
      <View className={styles.newsList}>
        {news.map(l => (
          <View
            className={clsx(styles.listItem, styles.seperatorLine)}
            key={l.id}
            onClick={() => navigation(pageMapper.newsDetail, { id: l.id })}
          >
            <Image src={l.picture} className={styles.listItemImage} />
            <View className={styles.listItemInfo}>
              <View className={styles.listItemTitle}>{l.title}</View>
              <View className={styles.listItemDesc}>
                <View>{l.publisher}</View>
                <View>{l.updatedRelativeTime}</View>
              </View>
            </View>
          </View>
        ))}
      </View>
    )
  }
  function renderTopics() {
    const topics = state.list as IApiRelative.ISearchWordTopic.IWordTopicListItem[]
    return (
      <View className="flex flex-col box-border relative">
        {/* list item for loop */}
        {topics.map(l => (
          <View
            key={l.id}
            className={clsx(styles1.listItem, styles.seperatorLine)}
            onClick={() => navigation(pageMapperCommunity.WordDetail, { id: l.id })}
          >
            <View className={styles1.imageWrap}>
              <Image src={l.thumbnail} className={styles1.image} />
            </View>
            <View className="flex-1 w-0">
              <View className="text-30px text-bold font-500 truncate"># {l.title}</View>
              <View className="text-24px text-light font-400 truncate mt-16px">
                {l.description}
              </View>
              <View className="flex flex-row gap-8px items-center box-border mt-24px">
                <ImageCascade images={l.miniVisitorHeads} />
                <View className="text-gray text-24px font-400">{l.viewCount}人浏览</View>
              </View>
            </View>
          </View>
        ))}
      </View>
    )
  }
  /**
   * 由于使用skyline实现瀑布流增加诸多兼容问题和复杂性, 故采用两列布局形式简单实现
   */
  function renderNotes() {
    const notes = state.list as IApiRelative.ISearchNotes.INoteListItem[]
    // 将笔记列表分两列显示成瀑布流布局
    const left = [] as IApiRelative.ISearchNotes.INoteListItem[]
    const right = [] as IApiRelative.ISearchNotes.INoteListItem[]
    notes.forEach((l, i) => {
      if (i % 2 === 0) {
        left.push(l)
      } else {
        right.push(l)
      }
    })
    return (
      <View className="flex flex-row gap-10px px-32px box-border py-16px">
        <View className="flex flex-col gap-10px box-border flex-1">
          {left.map(l => (
            <GpNoteItem
              skyline={false}
              key={l.id}
              noteItem={{
                id: l.id,
                actionFlag: false,
                avatar: l.createdByHead,
                fileType: l.fileType,
                image: l.thumbnail,
                liked: l.isSelfLike,
                likes: l.likeCount,
                name: l.createdByName,
                title: l.title,
                videoFlag: true,
                content: l.description
              }}
              onLike={handleLike}
            />
          ))}
        </View>
        <View className="flex flex-col gap-10px box-border flex-1">
          {right.map(l => (
            <GpNoteItem
              skyline={false}
              key={l.id}
              noteItem={{
                id: l.id,
                actionFlag: false,
                avatar: l.createdByHead,
                fileType: l.fileType,
                image: l.thumbnail,
                liked: l.isSelfLike,
                likes: l.likeCount,
                name: l.createdByName,
                title: l.title,
                videoFlag: true,
                content: l.description
              }}
              onLike={handleLike}
            />
          ))}
        </View>
      </View>
    )
  }
  return (
    <GpContainer className="min-h-screen">
      <View
        className={clsx("sticky top-0 z-50 bg-white", {
          "min-h-screen": !state.renderList
        })}
      >
        {renderSearchPanel()}
        {state.renderList ? renderFilters() : renderSearchHistory()}
      </View>
      {renderLists()}
    </GpContainer>
  )
}
